#include "error.h"
#include "../core/nodes/classnode.h"
#include "../core/nodes/operators.h"

Error::Error(AbstractNode * n): m_loc(n)
{
}

Error::~Error()
{
}

Warning::~Warning()
{
}

void Error::printWithPrelude()
{
	m_loc.print();
	printf(": ");
	print();
	printf("\n");
}
bool Error::operator<(const Error & o)
{
	int  cmps[3]={ m_loc.Filename.compare(o.m_loc.Filename),
		           m_loc.Line-o.m_loc.Line,
				   m_loc.Position-o.m_loc.Position
	             };
	for (int i=0;i<3;i++)
	{
		if (cmps[i]<0)  return true;
		else { if (cmps[i]>0) return false; }
	}
	return false;
}


DataRedefinitionError::DataRedefinitionError(AbstractNode * errorloc, 
			                                 AbstractNode * prevloc, 
					                         const std::string & objecttype,
					                         const std::string & objectname) 
: Error(errorloc),m_prev(prevloc),m_object_type(objecttype),m_object_name(objectname)
{
}

void DataRedefinitionError::print()
{
	printf("Error 1: %s - %s redefinition. ",m_object_name.c_str(),
											 m_object_type.c_str());
	if (m_prev.Position!=-1)
	{
	  printf("Previous declaration location: ");
	  m_prev.print();
	}
}


void LibraryClassRedefinitionError::print()
{
	printf("Error 2: %s - library class redefinition",m_name.c_str());
}


IncorrectTemplateArgumentCountError::IncorrectTemplateArgumentCountError(
	                                                                     AbstractNode * inh,
			                                                             std::string name,
											                             unsigned int needed,
											                             unsigned int real
																		)
:Error(inh),m_name(name),m_needed(needed),m_real(real)
{
}

void IncorrectTemplateArgumentCountError::print()
{
	printf("Error 3: %s - incorrect amount of arguments, must be %d instead of %d",
		   m_name.c_str(),
		   m_needed,
		   m_real
		  );
}
ClassDoesNotExistsError::ClassDoesNotExistsError(AbstractNode * node, const std::string & name)
: Error(node),m_name(name)
{
}

void ClassDoesNotExistsError::print()
{
	printf("Error 4: %s - class does not exists",m_name.c_str());
}


InheritanceLoopError::InheritanceLoopError(AbstractNode * node, const std::vector<std::string> & loop)
: Error(node),m_loop(loop)
{
}

void InheritanceLoopError::print()
{
  printf("Error 5: found an inheritance loop from other classes ");
  for (unsigned int i=0;i<m_loop.size();i++)
  {
	  printf("%s",m_loop[i].c_str());
	  if (i!=m_loop.size()-1)
		  printf(",");
  }
}

IncorrectOperatorSignature::IncorrectOperatorSignature(AbstractNode * node,const std::string & method, unsigned int n, unsigned int r)
: Error(node), m_needed(n),m_real(r),m_method(method)
{
}

void IncorrectOperatorSignature::print()
{
	printf("Error 6: incorrect operator signature must have %d arguments, instead of %d in method %s",
		   m_needed,m_real,m_method.c_str());
}


OperatorDoesNotExists::OperatorDoesNotExists(AbstractNode * node, 
											 const std::string & method, 
											 const std::string & name)
: Error(node),m_method(method),m_opname(name)
{
}

void OperatorDoesNotExists::print()
{
	printf("Error 7: operator \"%s\" for method %s does not exists",
		             m_opname.c_str(),m_method.c_str()
		  );
}

OperatorAlreadyDefined::OperatorAlreadyDefined(AbstractNode * node,
											   const std::string & opname,
											   const std::vector<std::string> & sig)
:Error(node),m_opname(opname),m_signature(sig)
{
  
}


void OperatorAlreadyDefined::print()
{
	printf("Error 8: operator \"%s\"(",m_opname.c_str());
	for(unsigned int i=0;i<m_signature.size();i++)
	{
		printf("%s",m_signature[i].c_str());
		if (i!=m_signature.size()-1)
			printf(",");
	}
	printf(") already defined");
}

OperatorField::OperatorField(AbstractNode * node): Error(node)
{
}

void OperatorField::print()
{
	printf("Error 9: class field cannot be an operator");
}

AbstractFrozen::AbstractFrozen(AbstractNode * node,const std::string & method)
:Error(node),m_methname(method)
{
}

void AbstractFrozen::print()
{
 printf("Error 10: abstract method is declared as frozen");
}

DuplicateRedefinition::DuplicateRedefinition(AbstractNode * node, const std::string & method)
:Error(node),m_method(method)
{
}

void DuplicateRedefinition::print()
{
 printf("Error 11: %s - duplicate method redefinition",m_method.c_str());
}

DuplicateRename::DuplicateRename(AbstractNode * node, const std::string & method)
:Error(node),m_oldname(method)
{
}

void DuplicateRename::print()
{
 printf("Error 12: %s - duplicate method rename",m_oldname.c_str());
}

EffectiveToAbstractReplace::EffectiveToAbstractReplace(AbstractNode * node, const std::string & method)
:Error(node),m_method(method)
{

}

void EffectiveToAbstractReplace::print()
{
	printf("Error 13: %s - effective method is replaced by abstract",m_method.c_str());
}


FrozenRedefinition::FrozenRedefinition(AbstractNode * node, const std::string & method)
: Error(node),m_method(method)
{
}

void FrozenRedefinition::print()
{
	printf("Error 14: %s - redefinition of frozen method",m_method.c_str());
}

ImplicitRedefinition::ImplicitRedefinition(AbstractNode * node, const std::string & method)
:Error(node),m_method(method)
{
}

void ImplicitRedefinition::print()
{
	printf("Error 15: %s - implicit redefinition of method",m_method.c_str());
}


AbstractFrozenClass::AbstractFrozenClass(ClassNode * node)
: Error(node),m_class_name(node->name())
{
}

void AbstractFrozenClass::print()
{
 printf("Error 16: %s - abstract class is declared as frozen",m_class_name.c_str());
}

ImplicitAbstractClass::ImplicitAbstractClass(ClassNode * node)
: Error(node),m_class_name(node->name())
{
}

void ImplicitAbstractClass::print()
{
 printf("Error 17: %s - abstract class is declared as effective",m_class_name.c_str());
}

FrozenInherited::FrozenInherited(ClassNode * node)
: Error(node),m_class_name(node->name())
{
}

void FrozenInherited::print()
{
 printf("Error 18: %s - a class inherits some frozen class",m_class_name.c_str());
}


MultipleInheritance::MultipleInheritance(ClassNode * node)
: Error(node),m_class_name(node->name())
{
}

void MultipleInheritance::print()
{
 printf("Error 19: %s - multiple inheritance is not supported",m_class_name.c_str());
}


RootClassDoesNotExists::RootClassDoesNotExists(const std::string &cname):Error(NULL), m_class(cname)
{
}

void RootClassDoesNotExists::print() 
{
 printf("Error 20: %s - root class does not exists",m_class.c_str());
}

RootMethodDoesNotExists::RootMethodDoesNotExists(ClassNode * node,const std::string & proc) 
: Error(node), m_name(node->name()),m_proc(proc)
{
}

void RootMethodDoesNotExists::print() 
{
 printf("Error 21: %s::%s root procedure does not exists",m_name.c_str(),m_proc.c_str());
}

RootMethodHasIncorrectSignature::RootMethodHasIncorrectSignature(ClassNode * node,const std::string & proc) 
: Error(node), m_name(node->name()),m_proc(proc)
{

}

void RootMethodHasIncorrectSignature::print()
{
 printf("Error 22: %s::%s root procedure has incorrect signature. Must do not return anything and has no arguments or ARRAY[STRING]",m_name.c_str(),m_proc.c_str());
}

MethodDoesNotExists::MethodDoesNotExists(IdentifierNode * node): Error(node)
{
 m_node=node->data();
}

MethodDoesNotExists::MethodDoesNotExists(ConverterNode  * node): Error(node)
{
 m_node=node->featureName();
}
void MethodDoesNotExists::print()
{
 printf("Error 23: %s - method does not exists",m_node.c_str());
}

ConstructorAlreadyDefined::ConstructorAlreadyDefined(IdentifierNode * node) : Error(node)
{
 m_node=node;
}

void ConstructorAlreadyDefined::print()
{
 printf("Error 24: %s - constructor already defined",m_node->data().c_str());
}

ConverterIsNotConstructor::ConverterIsNotConstructor(ConverterNode * node) : Error(node),m_node(node)
{
}

void ConverterIsNotConstructor::print()
{
 printf("Error 25: %s - converter procedure is not declared as a constructor",m_node->featureName().c_str());
}

TypeDoesNotExists::TypeDoesNotExists(ClassTypeNode * node) : Error(node)
{
	m_typename=node->fullName();
}

void TypeDoesNotExists::print()
{
	printf("Error 26: %s - type does not exists",m_typename.c_str());
}

TypeDoesNotExists::TypeDoesNotExists(AbstractNode * node, const std::string & type) 
: Error(node), m_typename(type)
{
}
IncorrectConverterSignature::IncorrectConverterSignature(ConverterNode * node): Error(node)
{
   m_node=node; 
}

void IncorrectConverterSignature::print()
{
	printf("Error 27: %s - incorrect converter signature. Converter procedures must accept one parameter and return nothing and queries are only return values",m_node->featureName().c_str());
}

NotEqualSignatureForConverter::NotEqualSignatureForConverter(ConverterNode * node): Error(node)
{
	m_node=node;
}

void NotEqualSignatureForConverter::print()
{
 printf("Error 28: %s - method and converter signatures are not equal",m_node->featureName().c_str());
}

ConverterAlreadyDefined::ConverterAlreadyDefined(ConverterNode * node) : Error(node)
{
  if (node->type()==CT_PROCEDURE)
	  m_direction="from";
  else
	  m_direction="to";
  m_type=(node->params()->vector()[0]->fullName());
}


void ConverterAlreadyDefined::print()
{
  printf("Error 29: converter %s type \"%s\" is already defined",m_direction.c_str(),m_type.c_str());
}

VariableShadowing::VariableShadowing(AbstractNode * node, const std::string & name): Error(node), m_name(name)
{
}

void VariableShadowing::print()
{
	printf("Error 30: %s - system variable shadowing",m_name.c_str());
}

LocalVariableShadowing::LocalVariableShadowing(AbstractNode * node, const std::string & name) : Warning(node),m_name(name)
{

}

void LocalVariableShadowing::print()
{
	printf("Warning 1: %s - formal argument is shadowed by local variable",m_name.c_str());
}

FieldOrMethodDoesNotExists::FieldOrMethodDoesNotExists(AbstractNode * node, 
		                        const std::string & name,
						        const std::string & type)
:Error(node),m_name(name),m_type(type)
{
}

void FieldOrMethodDoesNotExists::print()
{
  printf("Error 31: %s - field or method does not found in class %s",m_name.c_str(),m_type.c_str());
}

LocalVariableNotFound::LocalVariableNotFound(IdentifierNode * node) : Error(node),name(node->data())
{
}
LocalVariableNotFound::LocalVariableNotFound(AbstractNode * node,std::string _name) : Error(node),name(_name)
{
}
void LocalVariableNotFound::print()
{
  printf("Error 32: %s - local variable does not found",name.c_str());
}

OperatorMakesNoSense::OperatorMakesNoSense(OperatorNode * node) : Error(node),m_node(node)
{
}

void OperatorMakesNoSense::print()
{
  printf("Error 33: %s - operator here makes no sense. Consider removing this.",m_node->name().c_str());
}


ExpressionMakesNoSense::ExpressionMakesNoSense(AbstractNode * node) : Error(node)
{
}
void ExpressionMakesNoSense::print()
{
 printf("Error 34: expression makes no sense. Consider removing this.");
}

LeftOperandIsNotLValue::LeftOperandIsNotLValue(AbstractNode * node) : Error(node)
{
}

void LeftOperandIsNotLValue::print()
{
 printf("Error 35: left operand is not lvalue.");
}


NoResult::NoResult(AbstractNode * node) : Error(node)
{
  
}
void NoResult::print()
{
 printf("Error 36: control reaches the end of function, that returns a value.");
}


IncompatibleTypes::IncompatibleTypes(AbstractNode * node, const std::string & type1, const std::string & type2)
:Error(node), m_type1(type1),m_type2(type2)
{
}

void IncompatibleTypes::print()
{
  printf("Error 37: can't convert from type \"%s\" to \"%s\"",m_type1.c_str(),m_type2.c_str());
}

ConvertConform::ConvertConform(AbstractNode * node, 
							   const std::string & typefrom,
							   const std::string & typeto): Error(node),m_type1(typefrom),m_type2(typeto)
{
}

void ConvertConform::print()
{
  printf("Error 38: %s - type both conforms and converts to %s",m_type1.c_str(),m_type2.c_str());
}


MethodIsInaccessible::MethodIsInaccessible(AbstractNode * node, const std::string & name, const std::string & className)
:Error(node),m_name(name),m_className(className)
{
}

FieldIsInaccessible::FieldIsInaccessible(AbstractNode * node, const std::string & name, const std::string & className)
:Error(node),m_name(name),m_className(className)
{
}

AbstractPrecursorCall::AbstractPrecursorCall(AbstractNode * node, const std::string & name, const std::string & className )
:Error(node),m_name(name),m_className(className)
{
}

void AbstractPrecursorCall::print()
{
  printf("Error 39: attempt to call an abstract method %s from precursor %s",m_name.c_str(),m_className.c_str());
}

void FieldIsInaccessible::print()
{
  printf("Error 40: %s - field is inaccessible from class %s",m_name.c_str(),m_className.c_str());
}
void MethodIsInaccessible::print()
{
  printf("Error 41: %s - method is inaccessible from class %s",m_name.c_str(),m_className.c_str());
}


IncorrectAmountOfArguments::IncorrectAmountOfArguments(AbstractNode * node, int given, int real) : Error(node)
{
	m_given=given;
	m_real=real;
}

void IncorrectAmountOfArguments::print()
{
  printf("Error 42: incorrect amount of arguments given for method: %d instead of %d",m_given,m_real);
}

NotAnAncestor::NotAnAncestor(AbstractNode * node, const std::string & ancestor, const std::string & className)
: Error(node),m_ancestor(ancestor),m_class(className)
{
 
}

void NotAnAncestor::print()
{
 printf("Error 43: Tried to create polymorphic variable with no relationship between %s and %s",m_ancestor.c_str(),m_class.c_str());
}

PrecursorCurrentCreation::PrecursorCurrentCreation(AbstractNode * node) :  Error(node)
{
	
}

void PrecursorCurrentCreation::print()
{
 printf("Error 44: Attempted to replace CURRENT or PRECURSOR");
}

AbstractClassCreation::AbstractClassCreation(AbstractNode *node) : Error(node)
{
}

void AbstractClassCreation::print()
{
 printf("Error 45: Attempted to create abstract class");
}

NotAConstructor::NotAConstructor(AbstractNode * node) : Error(node)
{
}

void NotAConstructor::print()
{
	printf("Error 46: a method is not declared as a constructor");
}

ConstructorIsInaccessible::ConstructorIsInaccessible(AbstractNode * node, const std::string & name, const std::string & className)
:Error(node),m_name(name),m_className(className)
{
}

void ConstructorIsInaccessible::print()
{
	printf("Error 47: %s - constructor is inaccessible from class %s",m_name.c_str(),m_className.c_str());
}

AbstractRoot::AbstractRoot(AbstractNode * node): Error(node)
{
}

void AbstractRoot::print()
{
	printf("Error 48: root class cannot be abstract");
}

AbstractRootProcedure::AbstractRootProcedure(AbstractNode *node) : Error(node)
{
}

void AbstractRootProcedure::print()
{
	printf("Error 49: root procedure cannot be abstract");
}

VoidUsedInExpression::VoidUsedInExpression(AbstractNode * node) : Error(node)
{
}

void VoidUsedInExpression::print()
{
	printf("Error 50: VOID type used in expression");
}

CommonAncestorNotFound::CommonAncestorNotFound(AbstractNode * node) : Error(node)
{
}

void CommonAncestorNotFound::print()
{
 printf("Error 51: Cannot create compatible type; common ancestor not found");
}

OperatorOverloadNotFound::OperatorOverloadNotFound(AbstractNode * nodem,const std::string & name, const std::string & className,
												   const std::string & sarg, const std::string & targ)
:Error(nodem)
{
	m_name=name;
	m_class=className;
	m_vect.push_back(sarg);
	m_vect.push_back(targ);
}

OperatorOverloadNotFound::OperatorOverloadNotFound(AbstractNode * nodem,const std::string & name, const std::string & className,
												   const std::string & sarg)
:Error(nodem)
{
	m_name=name;
	m_class=className;
	m_vect.push_back(sarg);
}

OperatorOverloadNotFound::OperatorOverloadNotFound(AbstractNode * nodem,const std::string & name, const std::string & className)
:Error(nodem)
{
	m_name=name;
	m_class=className;
}

void OperatorOverloadNotFound::print()
{
	printf("Error 52: operator overload %s::%s(",m_class.c_str(),m_name.c_str());
	for (unsigned int i=0;i<m_vect.size();i++)
	{
		printf("%s",m_vect[i].c_str());
		if (i!=m_vect.size()-1)
			printf(",");
	}
	printf(") not found");
}


DuplicateInheritance::DuplicateInheritance(AbstractNode * node,const std::string & classname, const std::string inhclassname)
:Error(node),m_classname(classname),m_inherclassname(inhclassname)
{
}

void DuplicateInheritance::print()
{
	printf("Error 53: duplicate inheritance in the hierarchy class %s is multiple inherited %s",m_classname.c_str(),m_inherclassname.c_str());
}
